<?php
/**
*
*
*
*/
use Yz_Log_Log as Log;

class Yz_Exception
    extends Exception
{

    /** subclasses MAY redefine
     *
     */
    const ERROR_CODE = Log::CRITICAL;

    /** subclasses SHOULD define own messages
     *  @var string
     */
    protected $defaultMessage = "General exception";

    /**
     *  @var array
     */
    protected $values = array();

    /****************************
     *      Public methods      *
     ****************************/

    /**
     *  static shortcut for constructor
     *      Can be used in two forms (one argument, two arguments):
     *      - EX::_new(msg, array(args))
     *      - EX::_new(array(args))
     *  @param  string
     *  @param  array
     *  @return Yz_Exception
     */
    public static function _new($message=null, array $args=null)
    {
        if (null === $args) {
            if (is_array($message)) {
                $args = $message;
                $message = null;
            }
        }
        $ex = new static($message, null, null);
        #$tr = $ex->getTrace();
        #ob_start();
        #var_dump($tr);
        #debug(ob_get_clean());
        #array_shift($tr);
        #$ex->file = $tr[0]['file'];
        #$ex->line = $tr[0]['line'];
        if (null !== $args) {
            $ex->values = $args;
            Log::log( $ex->toString(), static::ERROR_CODE );
        }
        return $ex;
    }


    /**
    *   A handler may get parameters from
    *
    *   To ensure that messages may be safely localized
    *
    * @param string message: the message as above
    * @param int code: a code from list
    * @param Exception previous -> compatibility with 'Exception'
    *
    */
    public function __construct( $message=null, $code=null, $previous=null )
    {
        $message or $message = $this->defaultMessage;

        $code or $code = static::ERROR_CODE;

        parent::__construct( $message, $code, null );

        Log::log( sprintf( "%s at %s[%s]: %s",
                       get_class($this),
                       $this->file,
                       $this->line,
                       $this->message
              ),
              $code
        );
    } // __construct


    /**
    *
    */
    public function __toString()
    {
        try {
            $o = $this->toString();
        } catch (Exception $ex) {
            debug("toString Exception: ".$ex->getTraceAsString());
            $o = "Exception "
                . get_class($this)
                . ": "
                . $this->getFile()
                . ": "
                . $this->getLine()
                . ": "
                . $this->getMessage();
        }
        return $o;
    }


    /**
    *
    *
    */
    public function toString()
    {
        $msg = $this->message;
        if ( $this->values ) {
            $msg = Yz_String::replaceVars( $msg, $this->values );
        }

        $str = get_class( $this ) . " at {$this->file}@{$this->line}: {$msg}";

        return $str;
    } // toString



    /**
    *
    *
    */
    public function getLocaleMessage()
    {
        $msg = Yz_I18N_Default::getInstance()->translateWithParams(
            $this->message,
            $this->values
        );

        return $msg;
    }



    /**
     *
     *
     */
    public function withArgs( array $args )
    {
        $this->values = $args;

        Log::log( $this->toString(), static::ERROR_CODE );

        return $this;
    } // withArgs


} // class Yz_Exception

